<template>
  <canvas class="mining-map" ref="canvasRef"></canvas>
</template>

<script setup lang="ts">
import { useViewportStore } from '@/store/viewport'
import {
  AmbientLight,
  DirectionalLight,
  Group,
  PerspectiveCamera,
  Scene,
  Vector3,
  WebGLRenderer
} from 'three'
import { CSS2DRenderer, EffectComposer, OrbitControls } from 'three/examples/jsm/Addons'
import raycaster from './raycaster'
import heightlight from './highlight'
import controlsTarget from './controlsTarget'
import areaChange from './areaChange'
import { nextTick, onMounted, ref } from 'vue'
import addNodes from './addNodes'
import addPerson from './addPerson'
import useAnimationFrame from '@/hooks/useAnimationFrame'
import { getTunnelBaseInfo } from '@/api'

const {
  setCanvas,
  setScene,
  setPublicGroup,
  setNotPublicGroup,
  setCamera,
  setCss2DRenderer,
  setRenderer,
  setComposer,
  setOrbitControls,
  setBaseVec
} = useViewportStore()
const canvasRef = ref()

onMounted(async () => {
  // 初始化场景
  const { clientWidth, clientHeight } = canvasRef.value
  const renderer = new WebGLRenderer({
    logarithmicDepthBuffer: true,
    canvas: canvasRef.value,
    antialias: true,
    alpha: true
  })
  renderer.setClearColor(0x000000, 0)
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setSize(clientWidth, clientHeight)
  const camera = new PerspectiveCamera(75, clientWidth / clientHeight)
  camera.near = 0.1
  camera.far = 10000
  camera.updateProjectionMatrix()

  const scene = new Scene()
  // 创建一个公开组
  const publicGroup = new Group()
  publicGroup.name = 'publicGroup'
  const {data} = await getTunnelBaseInfo()
  const baseVec = new Vector3(data.xDrawString, 0, data.zDrawString)
  setBaseVec(baseVec)
  publicGroup.position.sub(baseVec);
  scene.add(publicGroup)
  // 创建一个内部使用，外部不可见的组
  const notPublicGroup = new Group()
  notPublicGroup.name = 'notPublicGroup'
  scene.add(notPublicGroup)

  const light = new AmbientLight(0xeeeeee) // 柔和的白光
  notPublicGroup.add(light)
  const directionalLight = new DirectionalLight(0xf4f4f4, 1)
  notPublicGroup.add(directionalLight)
  directionalLight.position.set(10, 10000, 50)

  const css2DRenderer = new CSS2DRenderer()
  css2DRenderer.setSize(clientWidth, clientHeight)
  css2DRenderer.domElement.style.position = 'absolute'
  css2DRenderer.domElement.style.zIndex = '10'
  css2DRenderer.domElement.setAttribute('class', 'css2DRenderer')
  css2DRenderer.domElement.style.top = '0px'
  canvasRef.value.parentNode.appendChild(css2DRenderer.domElement)
  camera.position.z = 5
  const orbitControls = new OrbitControls(camera, css2DRenderer.domElement)
  let initialDistance = camera.position.distanceTo(orbitControls.target)
  // 监听缩放变化
  orbitControls.addEventListener('change', () => {
    const currentDistance = camera.position.distanceTo(orbitControls.target)
    // console.log('当前缩放等级:', (currentDistance / initialDistance).toFixed(2))
    // 最大缩放5级 200一个单位，缩放比例 基础值2.97
    const scale = 5 - (currentDistance / initialDistance / 200).toFixed(2)
    document.documentElement.style.setProperty('--viewScale', Math.min(scale / 2.97, 1.5))
  })
  // 初始化后处理器
  const composer = new EffectComposer(renderer)
  composer.setPixelRatio(window.devicePixelRatio)
  // 加入状态管理
  setCanvas(canvasRef.value)
  setScene(scene)
  setCamera(camera)
  setCss2DRenderer(css2DRenderer)
  setRenderer(renderer)
  setOrbitControls(orbitControls)
  setPublicGroup(publicGroup)
  setNotPublicGroup(notPublicGroup)
  setComposer(composer)
  // 扩展
  raycaster()
  heightlight()
  controlsTarget()
  areaChange()
  // 动起来

  useAnimationFrame(() => {
    orbitControls.update()
    composer.render()
    css2DRenderer.render(scene, camera)
  })
 
  nextTick(async () => {
    await addNodes()
    setTimeout(() => {
      addPerson()
    }, 2000) // 延迟1s后执行addPerson函数，确保节点已经加载完再添加人物
  })

  // Resize
  window.addEventListener('resize', () => {
    const { clientWidth, clientHeight } = canvasRef.value
    camera.aspect = clientWidth / clientHeight
    camera.updateProjectionMatrix() // 更新摄像机投影矩阵
    renderer.setSize(clientWidth, clientHeight)
    css2DRenderer.setSize(clientWidth, clientHeight)
  })
})
</script>
<style lang="scss" scoped>
.mining-map {
  width: 100%;
  position: relative;
  background-color: transparent;
}
</style>
